package com.onmicro.snc_ble.core.bluetooth;

/**
 * Created by china on 2017/02/08.
 */

class OmrCRC16 {
    /*  Ansi-OmrCRC16: X16+X15+X2+1  */
    static private final int[] ANSI_CRC16_TABLE = {
                        0x0000,  0x8005,  0x800F,  0x000A,  0x801B,  0x001E,  0x0014,  0x8011,    
                        0x8033,  0x0036,  0x003C,  0x8039,  0x0028,  0x802D,  0x8027,  0x0022,    
                        0x8063,  0x0066,  0x006C,  0x8069,  0x0078,  0x807D,  0x8077,  0x0072,    
                        0x0050,  0x8055,  0x805F,  0x005A,  0x804B,  0x004E,  0x0044,  0x8041,    
                        0x80C3,  0x00C6,  0x00CC,  0x80C9,  0x00D8,  0x80DD,  0x80D7,  0x00D2,    
                        0x00F0,  0x80F5,  0x80FF,  0x00FA,  0x80EB,  0x00EE,  0x00E4,  0x80E1,    
                        0x00A0,  0x80A5,  0x80AF,  0x00AA,  0x80BB,  0x00BE,  0x00B4,  0x80B1,    
                        0x8093,  0x0096,  0x009C,  0x8099,  0x0088,  0x808D,  0x8087,  0x0082,    
                        0x8183,  0x0186,  0x018C,  0x8189,  0x0198,  0x819D,  0x8197,  0x0192,    
                        0x01B0,  0x81B5,  0x81BF,  0x01BA,  0x81AB,  0x01AE,  0x01A4,  0x81A1,    
                        0x01E0,  0x81E5,  0x81EF,  0x01EA,  0x81FB,  0x01FE,  0x01F4,  0x81F1,    
                        0x81D3,  0x01D6,  0x01DC,  0x81D9,  0x01C8,  0x81CD,  0x81C7,  0x01C2,    
                        0x0140,  0x8145,  0x814F,  0x014A,  0x815B,  0x015E,  0x0154,  0x8151,    
                        0x8173,  0x0176,  0x017C,  0x8179,  0x0168,  0x816D,  0x8167,  0x0162,    
                        0x8123,  0x0126,  0x012C,  0x8129,  0x0138,  0x813D,  0x8137,  0x0132,    
                        0x0110,  0x8115,  0x811F,  0x011A,  0x810B,  0x010E,  0x0104,  0x8101,    
                        0x8303,  0x0306,  0x030C,  0x8309,  0x0318,  0x831D,  0x8317,  0x0312,    
                        0x0330,  0x8335,  0x833F,  0x033A,  0x832B,  0x032E,  0x0324,  0x8321,    
                        0x0360,  0x8365,  0x836F,  0x036A,  0x837B,  0x037E,  0x0374,  0x8371,    
                        0x8353,  0x0356,  0x035C,  0x8359,  0x0348,  0x834D,  0x8347,  0x0342,    
                        0x03C0,  0x83C5,  0x83CF,  0x03CA,  0x83DB,  0x03DE,  0x03D4,  0x83D1,    
                        0x83F3,  0x03F6,  0x03FC,  0x83F9,  0x03E8,  0x83ED,  0x83E7,  0x03E2,    
                        0x83A3,  0x03A6,  0x03AC,  0x83A9,  0x03B8,  0x83BD,  0x83B7,  0x03B2,    
                        0x0390,  0x8395,  0x839F,  0x039A,  0x838B,  0x038E,  0x0384,  0x8381,    
                        0x0280,  0x8285,  0x828F,  0x028A,  0x829B,  0x029E,  0x0294,  0x8291,    
                        0x82B3,  0x02B6,  0x02BC,  0x82B9,  0x02A8,  0x82AD,  0x82A7,  0x02A2,    
                        0x82E3,  0x02E6,  0x02EC,  0x82E9,  0x02F8,  0x82FD,  0x82F7,  0x02F2,    
                        0x02D0,  0x82D5,  0x82DF,  0x02DA,  0x82CB,  0x02CE,  0x02C4,  0x82C1,    
                        0x8243,  0x0246,  0x024C,  0x8249,  0x0258,  0x825D,  0x8257,  0x0252,    
                        0x0270,  0x8275,  0x827F,  0x027A,  0x826B,  0x026E,  0x0264,  0x8261,    
                        0x0220,  0x8225,  0x822F,  0x022A,  0x823B,  0x023E,  0x0234,  0x8231,    
                        0x8213,  0x0216,  0x021C,  0x8219,  0x0208,  0x820D,  0x8207,  0x0202,
    };
  

/*  Ansi-OmrCRC16-Reverse: X16+X15+X2+1  */
    static private final int[] ANSI_CRC16R_TABLE = {
                        0x0000,  0xC0C1,  0xC181,  0x0140,  0xC301,  0x03C0,  0x0280,  0xC241,    
                        0xC601,  0x06C0,  0x0780,  0xC741,  0x0500,  0xC5C1,  0xC481,  0x0440,    
                        0xCC01,  0x0CC0,  0x0D80,  0xCD41,  0x0F00,  0xCFC1,  0xCE81,  0x0E40,    
                        0x0A00,  0xCAC1,  0xCB81,  0x0B40,  0xC901,  0x09C0,  0x0880,  0xC841,    
                        0xD801,  0x18C0,  0x1980,  0xD941,  0x1B00,  0xDBC1,  0xDA81,  0x1A40,    
                        0x1E00,  0xDEC1,  0xDF81,  0x1F40,  0xDD01,  0x1DC0,  0x1C80,  0xDC41,    
                        0x1400,  0xD4C1,  0xD581,  0x1540,  0xD701,  0x17C0,  0x1680,  0xD641,    
                        0xD201,  0x12C0,  0x1380,  0xD341,  0x1100,  0xD1C1,  0xD081,  0x1040,    
                        0xF001,  0x30C0,  0x3180,  0xF141,  0x3300,  0xF3C1,  0xF281,  0x3240,    
                        0x3600,  0xF6C1,  0xF781,  0x3740,  0xF501,  0x35C0,  0x3480,  0xF441,    
                        0x3C00,  0xFCC1,  0xFD81,  0x3D40,  0xFF01,  0x3FC0,  0x3E80,  0xFE41,    
                        0xFA01,  0x3AC0,  0x3B80,  0xFB41,  0x3900,  0xF9C1,  0xF881,  0x3840,    
                        0x2800,  0xE8C1,  0xE981,  0x2940,  0xEB01,  0x2BC0,  0x2A80,  0xEA41,    
                        0xEE01,  0x2EC0,  0x2F80,  0xEF41,  0x2D00,  0xEDC1,  0xEC81,  0x2C40,    
                        0xE401,  0x24C0,  0x2580,  0xE541,  0x2700,  0xE7C1,  0xE681,  0x2640,    
                        0x2200,  0xE2C1,  0xE381,  0x2340,  0xE101,  0x21C0,  0x2080,  0xE041,    
                        0xA001,  0x60C0,  0x6180,  0xA141,  0x6300,  0xA3C1,  0xA281,  0x6240,    
                        0x6600,  0xA6C1,  0xA781,  0x6740,  0xA501,  0x65C0,  0x6480,  0xA441,    
                        0x6C00,  0xACC1,  0xAD81,  0x6D40,  0xAF01,  0x6FC0,  0x6E80,  0xAE41,    
                        0xAA01,  0x6AC0,  0x6B80,  0xAB41,  0x6900,  0xA9C1,  0xA881,  0x6840,    
                        0x7800,  0xB8C1,  0xB981,  0x7940,  0xBB01,  0x7BC0,  0x7A80,  0xBA41,    
                        0xBE01,  0x7EC0,  0x7F80,  0xBF41,  0x7D00,  0xBDC1,  0xBC81,  0x7C40,    
                        0xB401,  0x74C0,  0x7580,  0xB541,  0x7700,  0xB7C1,  0xB681,  0x7640,    
                        0x7200,  0xB2C1,  0xB381,  0x7340,  0xB101,  0x71C0,  0x7080,  0xB041,    
                        0x5000,  0x90C1,  0x9181,  0x5140,  0x9301,  0x53C0,  0x5280,  0x9241,    
                        0x9601,  0x56C0,  0x5780,  0x9741,  0x5500,  0x95C1,  0x9481,  0x5440,    
                        0x9C01,  0x5CC0,  0x5D80,  0x9D41,  0x5F00,  0x9FC1,  0x9E81,  0x5E40,    
                        0x5A00,  0x9AC1,  0x9B81,  0x5B40,  0x9901,  0x59C0,  0x5880,  0x9841,    
                        0x8801,  0x48C0,  0x4980,  0x8941,  0x4B00,  0x8BC1,  0x8A81,  0x4A40,    
                        0x4E00,  0x8EC1,  0x8F81,  0x4F40,  0x8D01,  0x4DC0,  0x4C80,  0x8C41,    
                        0x4400,  0x84C1,  0x8581,  0x4540,  0x8701,  0x47C0,  0x4680,  0x8641,    
                        0x8201,  0x42C0,  0x4380,  0x8341,  0x4100,  0x81C1,  0x8081,  0x4040,    
    };
  
/* CCITT-OmrCRC16: X16+X12+X5+1  */
    static private final int[] CCITT_CRC16_TABLE = {
                        0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50A5,  0x60C6,  0x70E7,    
                        0x8108,  0x9129,  0xA14A,  0xB16B,  0xC18C,  0xD1AD,  0xE1CE,  0xF1EF,    
                        0x1231,  0x0210,  0x3273,  0x2252,  0x52B5,  0x4294,  0x72F7,  0x62D6,    
                        0x9339,  0x8318,  0xB37B,  0xA35A,  0xD3BD,  0xC39C,  0xF3FF,  0xE3DE,    
                        0x2462,  0x3443,  0x0420,  0x1401,  0x64E6,  0x74C7,  0x44A4,  0x5485,    
                        0xA56A,  0xB54B,  0x8528,  0x9509,  0xE5EE,  0xF5CF,  0xC5AC,  0xD58D,    
                        0x3653,  0x2672,  0x1611,  0x0630,  0x76D7,  0x66F6,  0x5695,  0x46B4,    
                        0xB75B,  0xA77A,  0x9719,  0x8738,  0xF7DF,  0xE7FE,  0xD79D,  0xC7BC,    
                        0x48C4,  0x58E5,  0x6886,  0x78A7,  0x0840,  0x1861,  0x2802,  0x3823,    
                        0xC9CC,  0xD9ED,  0xE98E,  0xF9AF,  0x8948,  0x9969,  0xA90A,  0xB92B,    
                        0x5AF5,  0x4AD4,  0x7AB7,  0x6A96,  0x1A71,  0x0A50,  0x3A33,  0x2A12,    
                        0xDBFD,  0xCBDC,  0xFBBF,  0xEB9E,  0x9B79,  0x8B58,  0xBB3B,  0xAB1A,    
                        0x6CA6,  0x7C87,  0x4CE4,  0x5CC5,  0x2C22,  0x3C03,  0x0C60,  0x1C41,    
                        0xEDAE,  0xFD8F,  0xCDEC,  0xDDCD,  0xAD2A,  0xBD0B,  0x8D68,  0x9D49,    
                        0x7E97,  0x6EB6,  0x5ED5,  0x4EF4,  0x3E13,  0x2E32,  0x1E51,  0x0E70,    
                        0xFF9F,  0xEFBE,  0xDFDD,  0xCFFC,  0xBF1B,  0xAF3A,  0x9F59,  0x8F78,    
                        0x9188,  0x81A9,  0xB1CA,  0xA1EB,  0xD10C,  0xC12D,  0xF14E,  0xE16F,    
                        0x1080,  0x00A1,  0x30C2,  0x20E3,  0x5004,  0x4025,  0x7046,  0x6067,    
                        0x83B9,  0x9398,  0xA3FB,  0xB3DA,  0xC33D,  0xD31C,  0xE37F,  0xF35E,    
                        0x02B1,  0x1290,  0x22F3,  0x32D2,  0x4235,  0x5214,  0x6277,  0x7256,    
                        0xB5EA,  0xA5CB,  0x95A8,  0x8589,  0xF56E,  0xE54F,  0xD52C,  0xC50D,    
                        0x34E2,  0x24C3,  0x14A0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,    
                        0xA7DB,  0xB7FA,  0x8799,  0x97B8,  0xE75F,  0xF77E,  0xC71D,  0xD73C,    
                        0x26D3,  0x36F2,  0x0691,  0x16B0,  0x6657,  0x7676,  0x4615,  0x5634,    
                        0xD94C,  0xC96D,  0xF90E,  0xE92F,  0x99C8,  0x89E9,  0xB98A,  0xA9AB,    
                        0x5844,  0x4865,  0x7806,  0x6827,  0x18C0,  0x08E1,  0x3882,  0x28A3,    
                        0xCB7D,  0xDB5C,  0xEB3F,  0xFB1E,  0x8BF9,  0x9BD8,  0xABBB,  0xBB9A,    
                        0x4A75,  0x5A54,  0x6A37,  0x7A16,  0x0AF1,  0x1AD0,  0x2AB3,  0x3A92,    
                        0xFD2E,  0xED0F,  0xDD6C,  0xCD4D,  0xBDAA,  0xAD8B,  0x9DE8,  0x8DC9,    
                        0x7C26,  0x6C07,  0x5C64,  0x4C45,  0x3CA2,  0x2C83,  0x1CE0,  0x0CC1,    
                        0xEF1F,  0xFF3E,  0xCF5D,  0xDF7C,  0xAF9B,  0xBFBA,  0x8FD9,  0x9FF8,    
                        0x6E17,  0x7E36,  0x4E55,  0x5E74,  0x2E93,  0x3EB2,  0x0ED1,  0x1EF0,    
    };
  

/*  CCITT-OmrCRC16-Reverse: X16+X12+X5+1 */
    static private final int[] CCITT_CRC16R_TABLE = {
                        0x0000,  0x1189,  0x2312,  0x329B,  0x4624,  0x57AD,  0x6536,  0x74BF,    
                        0x8C48,  0x9DC1,  0xAF5A,  0xBED3,  0xCA6C,  0xDBE5,  0xE97E,  0xF8F7,    
                        0x1081,  0x0108,  0x3393,  0x221A,  0x56A5,  0x472C,  0x75B7,  0x643E,    
                        0x9CC9,  0x8D40,  0xBFDB,  0xAE52,  0xDAED,  0xCB64,  0xF9FF,  0xE876,    
                        0x2102,  0x308B,  0x0210,  0x1399,  0x6726,  0x76AF,  0x4434,  0x55BD,    
                        0xAD4A,  0xBCC3,  0x8E58,  0x9FD1,  0xEB6E,  0xFAE7,  0xC87C,  0xD9F5,    
                        0x3183,  0x200A,  0x1291,  0x0318,  0x77A7,  0x662E,  0x54B5,  0x453C,    
                        0xBDCB,  0xAC42,  0x9ED9,  0x8F50,  0xFBEF,  0xEA66,  0xD8FD,  0xC974,    
                        0x4204,  0x538D,  0x6116,  0x709F,  0x0420,  0x15A9,  0x2732,  0x36BB,    
                        0xCE4C,  0xDFC5,  0xED5E,  0xFCD7,  0x8868,  0x99E1,  0xAB7A,  0xBAF3,    
                        0x5285,  0x430C,  0x7197,  0x601E,  0x14A1,  0x0528,  0x37B3,  0x263A,    
                        0xDECD,  0xCF44,  0xFDDF,  0xEC56,  0x98E9,  0x8960,  0xBBFB,  0xAA72,    
                        0x6306,  0x728F,  0x4014,  0x519D,  0x2522,  0x34AB,  0x0630,  0x17B9,    
                        0xEF4E,  0xFEC7,  0xCC5C,  0xDDD5,  0xA96A,  0xB8E3,  0x8A78,  0x9BF1,    
                        0x7387,  0x620E,  0x5095,  0x411C,  0x35A3,  0x242A,  0x16B1,  0x0738,    
                        0xFFCF,  0xEE46,  0xDCDD,  0xCD54,  0xB9EB,  0xA862,  0x9AF9,  0x8B70,    
                        0x8408,  0x9581,  0xA71A,  0xB693,  0xC22C,  0xD3A5,  0xE13E,  0xF0B7,    
                        0x0840,  0x19C9,  0x2B52,  0x3ADB,  0x4E64,  0x5FED,  0x6D76,  0x7CFF,    
                        0x9489,  0x8500,  0xB79B,  0xA612,  0xD2AD,  0xC324,  0xF1BF,  0xE036,    
                        0x18C1,  0x0948,  0x3BD3,  0x2A5A,  0x5EE5,  0x4F6C,  0x7DF7,  0x6C7E,    
                        0xA50A,  0xB483,  0x8618,  0x9791,  0xE32E,  0xF2A7,  0xC03C,  0xD1B5,    
                        0x2942,  0x38CB,  0x0A50,  0x1BD9,  0x6F66,  0x7EEF,  0x4C74,  0x5DFD,    
                        0xB58B,  0xA402,  0x9699,  0x8710,  0xF3AF,  0xE226,  0xD0BD,  0xC134,    
                        0x39C3,  0x284A,  0x1AD1,  0x0B58,  0x7FE7,  0x6E6E,  0x5CF5,  0x4D7C,    
                        0xC60C,  0xD785,  0xE51E,  0xF497,  0x8028,  0x91A1,  0xA33A,  0xB2B3,    
                        0x4A44,  0x5BCD,  0x6956,  0x78DF,  0x0C60,  0x1DE9,  0x2F72,  0x3EFB,    
                        0xD68D,  0xC704,  0xF59F,  0xE416,  0x90A9,  0x8120,  0xB3BB,  0xA232,    
                        0x5AC5,  0x4B4C,  0x79D7,  0x685E,  0x1CE1,  0x0D68,  0x3FF3,  0x2E7A,    
                        0xE70E,  0xF687,  0xC41C,  0xD595,  0xA12A,  0xB0A3,  0x8238,  0x93B1,    
                        0x6B46,  0x7ACF,  0x4854,  0x59DD,  0x2D62,  0x3CEB,  0x0E70,  0x1FF9,    
                        0xF78F,  0xE606,  0xD49D,  0xC514,  0xB1AB,  0xA022,  0x92B9,  0x8330,    
                        0x7BC7,  0x6A4E,  0x58D5,  0x495C,  0x3DE3,  0x2C6A,  0x1EF1,  0x0F78,    
    };

    static int get_crc16(final int[] table, final byte[] data, final int start, final int length, final int crc_init){

        int crc = crc_init & 0xFFFF;
        for (int i = 0; i < Math.min(length, data.length); i++) {
            crc = (crc<<8) ^ table[(data[start + i] ^ (crc>>>8)) & 0x00FF];
        }
        return crc;
    }

    static int get_crc16r(final int[] table, final byte[] data, final int start, final int length, final int crc_init){

        int crc = crc_init & 0xFFFF;
        for (int i = 0; i < Math.min(length, data.length); i++) {
            crc = (crc>>>8) ^ table[(data[start + i] ^ crc) & 0x00FF];
        }
        return crc;
    }

    /*  ansi-crc16 */
    static int get_ansi_crc16(byte[] data, int start, int length, int crc_init)
    {
        return get_crc16(ANSI_CRC16_TABLE, data, start, length, crc_init);
    }

    /*  ansi-crc16-reverse  */
    static int get_ansi_crc16r(byte[] data, int start, int length, int crc_init)
    {
        return get_crc16r(ANSI_CRC16R_TABLE, data, start, length, crc_init);
    }
  
    /*  ccitt-crc16  */
    static int get_ccitt_crc16(byte[] data, int start, int length, int crc_init)
    {
        return get_crc16(CCITT_CRC16_TABLE, data, start, length, crc_init);
    }

    /*  ccitt-crc16-reverse */
    static int get_ccitt_crc16r(byte[] data, int start, int length, int crc_init)
    {
        return get_crc16r(CCITT_CRC16R_TABLE, data, start, length, crc_init);
    }

}
